﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Informaiton_Retrieval.com.ir.utli;
using System.IO;
using Informaiton_Retrieval_Hw2.com.Model;
using System.Text.RegularExpressions;
using Informaiton_Retrieval_Hw2.com.Utli;
using System.Threading.Tasks;

namespace Informaiton_Retrieval_Hw2.com.Model
{
    class Model
    {
        SymSpell spellcor = new SymSpell();
        IndexDictionary index;
        public bool isLoading = false;
        public bool isSearching = false;
        public bool isLoaded = false;
        public int Percent { get; set; }

        public delegate void UpdateUIHandler();
        public UpdateUIHandler updateUIEvent;

        public delegate void UpdateCorrectQueryHandler();
        public UpdateCorrectQueryHandler updateCorrectQueryEvent;

        DocumentData data;
        String token;
        int tokenCount;

        public string outPut = "";

        public Model()
        {
            index = new IndexDictionary();
        }

        long fileLines;

        public void Load(string filePath)
        {
            Task.Factory.StartNew(() =>
            {
                isLoading = true;
                isLoaded = false;
                updateView();
                fileLines = CalculateLines(filePath);
                load(filePath);
                isLoading = false;
                isLoaded = true;
                updateView();
            });
        }

        private void load(string filePath)
        {
            using (StreamReader sr = new StreamReader(filePath, Encoding.UTF8))
            {
                List<string> termList = new List<string>();
                string line;
                string[] temp;
                data = new DocumentData();
                token = "";
                tokenCount = 0;
                long lineCount = 0;
                while ((line = sr.ReadLine()) != null)
                {
                    InitIndexContent();
                    temp = line.Split(':');
                    String info1 = temp[0];
                    String info2 = "";

                    for (int i = 1; i < temp.Length; i++)
                    {
                        info2 += temp[i];
                    }

                    token = info1.Split(',')[0];
                    tokenCount = Convert.ToInt32(info1.Split(',')[1]);

                    temp = info2.Split(';');

                    for (int i = 0; i < temp.Length; i++)
                    {
                        if (temp[i].Contains("<"))
                        {//<clueweb09-enwp00-02-00004,2<5180,8000>
                            String[] strArray = temp[i].Split('<', ',', '>');
                            String docId = strArray[1];
                            data.counter = tokenCount;
                            List<int> posList = new List<int>();
                            for (int j = 0; j < Convert.ToInt32(strArray[2]); j++)
                            {
                                posList.Add(Convert.ToInt32(strArray[3 + j]));    //
                            }
                            data._dicPos.Add(docId, posList);
                        }
                    }

                    index.Add(token, data);
                    termList.Add(token);
                    lineCount++;
                    loadProgress(lineCount);
                }
                spellcor.CreateDictionary(termList, "en");
            }
            isLoaded = true;
        }

        private long CalculateLines(string filePath)
        {
            using (StreamReader sr = new StreamReader(filePath, Encoding.UTF8))
            {
                long _fileLines = 0;
                while (sr.ReadLine() != null)
                {
                    _fileLines++;
                }
                return _fileLines;
            }
        }

        void loadProgress(long lineCount)
        {
            int percent = (int)((float)lineCount * 100f / (float)fileLines);
            updateProgress(percent);
        }

        public void Search(string queryText)
        {
            int temp = 0;
            string[] query = Regex.Split(queryText, @"\W+|_");
            query = Tokenization.FiltNumber(query);
            query = Tokenization.LowerCase(query);
            foreach (String queryCor in query)
            {
                query[temp] = spellcor.Correct(queryCor, "en");
                correctQueryText += query[temp] + " ";
                temp++;
            }

            if (updateCorrectQueryEvent != null)
            {
                updateCorrectQueryEvent();
            }

            Task.Factory.StartNew(() =>
            {
                isSearching = true;
                updateView();
                search(query);
                isSearching = false;
                updateView();
            });
        }

        void updateProgress(int percent)
        {
            Percent = percent;
            updateView();
        }

        private void updateView()
        {
            if (updateUIEvent != null)
            {
                updateUIEvent();
            }
        }

        private void search(string[] query)
        {
            TF_IDFWeightHelper helper = new TF_IDFWeightHelper(index);
            helper.updateEvent += this.updateProgress;
            List<DocumentScore> scores = helper.GetScores(query);

            TextWriter tw = new StreamWriter("Score.txt", false, Encoding.UTF8);
            foreach (DocumentScore ds in scores)
                tw.WriteLine(ds.DocumentId + "," + ds.Score);
            tw.Close();
            outPut = "";
            foreach (DocumentScore ds in scores)
            {
                outPut += "<"+ds.DocumentId + ">," + ds.Score + "\r\n";
            }
            updateView();
        }

        private void InitIndexContent()
        {
            data = new DocumentData();
            token = "";
            tokenCount = 0;
        }

        public string correctQueryText;
        public void simpleSearch(string queryText)
        {
            queryText = spellcor.Correct(queryText, "en");
            correctQueryText = queryText;
            if (updateCorrectQueryEvent != null)
            {
                updateCorrectQueryEvent();
            }
            outPut = "";

            if (index.ContainsKey(queryText))
            {
                foreach (string key2 in index[queryText]._dicPos.Keys)
                {
                    outPut += key2 + "\r\n";
                }
            }
            else
            {
                outPut = "No Result!";
            }
            updateView();
        }
    }
}
